Welcome back.
In this lecture.
We're going to be working on the sprinting system for our players.
If you remember we have a stamina guy inside of starter guy here.
And this guy is going to be representing how much stamina a player has left.
So when a player gets a character, we need to listen for when that player sprints and when they do,
we should increase their speed and start taking away stamina.
If you were in my previous course, the sprinting system we're going to be making here is basically
going to be the exact same one as we created in the project for that previous course.
So let's go ahead and get started inside of starter character scripts, we're going to open our sprint
guy handler.
And inside of here we're going to need four services.
One is going to be the player service.
We're going to need a service called the Context Action Service.
That way we can listen to when a specific key is pressed.
We're going to need the tween service to tween UI elements, and we're also going to need the run service
because we're going to be updating the stamina bar basically every frame.
Now some references we're going to have to make to stuff in here.
One is going to be the players camera.
So workspace dot current camera because when the player sprints we want to give the effect that they're
moving faster by increasing their field of view.
And then when they stop sprinting, we can return the field of view on the camera back to its previous
one.
We want to have a reference to the local player.
Because we need to get the player's character.
So player dot character or we can do player dot character added weight.
This is always a good practice to do, even though it's kind of redundant in here because the script
is inside of starter character scripts.
We don't have to actually wait for the character to be added, but I always include it anyways, because
there will be times in other scripts where you might need to actually wait for the character to replicate,
and if you don't ever include it, you might forget to do it and you'll run into issues later down the
line.
So I just include it just in case.
But you're not going to have to for any script that is inside of starter character scripts.
And the next we're going to make a reference to the humanoid, and we can denote it as the humanoid.
So character weight for child humanoid.
We're going to make a reference to our sprinting guy.
So we'll just call it guy.
And that's inside of the players player guy folder.
And we need to wait for this guy to replicate.
And then we're going to create some other variables.
One is going to keep track of our current stamina.
And right now we'll set it to 100.
We're also going to create.
A variable to keep track of the camera's original field of view, so we'll call it a ridge FOV, which
is equal to the camera dot field of view.
And then we're going to have some other booleans in here, one that's going to tell us whether or not
the player has their shift key down.
And we'll set that to false for now.
Another one is we're going to have a boolean to keep track of a sprinting cooldown.
So sprinting cooldown.
Is equal to false.
And then we're going to have a Boolean to tell us whether or not we can replenish stamina.
So can replenish stamina.
And we'll set that to true.
Now another thing I'm going to do is I'm going to store a function, a global function in local memory.
And that's for creating a new Udim two.
So we're going to call this new Udim two.
And it's going to be equal to the Udim two dot new function.
And this is because since we're going to be updating the stamina guy basically every single frame,
it's more performant for us to access a function in local memory than it is for us to grab it from a
global memory, or basically trying to get this global function from our game's data model.
Now we're going to also define some constants here.
One constant is going to be the speed at which we will be sprinting.
So in this case our sprinting speed will be 24 studs per second.
We'll store the regular speed of our player's character.
So that'll be humanoid dot walk speed.
We want to store the max stamina a player can have, which would be 100.
We want to store how much to reduce our stamina by, and this number is going to represent how much
stamina to remove from our current stamina every second.
So for example, I found that the number of 18 is good.
So every second will have 18 numbers removed from our 100, uh, when we're sprinting.
And then we'll also create a variable for increasing the stamina or recovering the stamina.
And you'll want to make sure that this number is lower than reducing the stamina, because we want to
make it harder for them to regain stamina than to lose stamina.
Then we're going to create a constant that will represent the field of view for when we're sprinting.
And that's going to be 85 degrees.
And then we're also going to, uh, create a constant that will represent the cooldown for when a player
reaches zero stamina.
And we're going to set that to five seconds.
So if a player is sprinting and their stamina goes all the way down to zero, then we want to wait for
five seconds before we can actually start replenishing stamina again.
So in here, the only private function we're going to need is a function to update our stamina bar.
And we're going to call it update stamina bar.
And then the events we're going to have to listen into here are only two.
The first event is going to be within the Context Action Service.
And what we want to do is we want to bind an action to a particular key.
And the name we're going to give for this action is shift to sprint.
And the function we want to bind will be a lambda function here.
And then there's some other stuff we have to pass to this function.
One will be a boolean for creating a touch button.
And this will be on mobile devices.
But since our game isn't going to support mobile devices, I'm just going to set this to false for now.
And then we need to pass the key that we need to attach this action to.
And that's going to be enum dot Keycode dot left shift.
So when a player holds down the left shift key then we're going to start sprinting.
So that means inside of this lambda function, we're going to get passed the name of the action and
then the input state for our player.
And what we're going to do in this function is we're going to make sure that the input state is in the
beginning stages.
So if input state is equal to enum dot user input state dot begin.
Or basically we're beginning to push the key down.
Then what we need to do is we need to set our shift down variable equal to true.
Otherwise, if our input state is equal to the enum dot user input state dot end, then we're going
to set shift down equal to false.
So when a player presses down a key, it'll give us the begin input state.
And when a player lifts up the key it'll give us the end input state.
Now one other thing we're going to have to make sure is that we actually have enough stamina to set
this variable to true here.
So if our current stamina is less than or equal to zero, then we're just going to return out of this
function.
Now the next event we need to listen to is inside of our run service.
And that's the heartbeat event.
So every single heartbeat we're going to be updating our sprinting guy.
And this function is going to get passed something called a delta time, or basically this number represents
the amount of time between frames.
So when this event gets fired, it'll get passed the amount of time it took from the last time this
event fired.
So let's say this event gets fired right?
And then it gets fired again.
The difference in time between those two events firing is what gets passed to this function.
And we're going to call it Delta time.
Now what we have to do in here is we need to check whether or not our shift is being held down.
And if it is, we need to start sprinting and reducing stamina.
So if our shift key is being held down, and we also want to make sure that our current stamina is greater
than zero, and we also want to make sure our player is actually moving, because if the player isn't
moving, let's say they're just sitting there and they're holding the shift key down.
It's going to reduce stamina even if we're not moving.
So we need to make sure our humanoid dot move direction dot magnitude is greater than zero.
Now, the first thing we should check is whether or not our camera's field of view is set to the sprint
field of view.
Because if it isn't, then we need to zoom our camera out to give the illusion that we're moving faster.
So if the camera dot field of view is not equal to the sprint field of view, then what we need to do
is we need to create a tween.
We're going to use the tween service and create a tween on our camera.
And we can make this tween last something like 0.8 seconds.
And what we need to change on our camera is the field of view.
And we're going to set that equal to the sprint field of view.
And then we can just play this tween.
Afterwards.
While we are sprinting, we want to continue to make sure that the humanoids walk.
Speed is equal to the sprint speed, and then we also want to make sure that we're reducing the stamina
of our player so we can do current.
Stamina is minus equal to our stamina reduce.
And then we're going to multiply this by our delta time.
Because basically what's going to be happening is that there may be some inconsistencies when this event
gets fired, because some players might be running the game at higher frame rates than other players.
And if that's the case, we still want to decrease the stamina by the same amount, or we want to take
the same amount of time to reduce our stamina.
So that way it's the same for every player, regardless of their frame rate.
So that's why it's important that we multiply our stamina reduce by the delta time, or aka how much
time it took between the heartbeats.
So for example, let's say the player's frame rate all of a sudden drops.
Then that means the delta time is going to increase, and when the delta time increases, that means
the amount that we're going to reduce our current stamina by is also going to increase.
Otherwise, if we don't have our shift key held down, then we need to reset the field of view of our
camera.
So if the camera dot field of view is not equal to the original field of view, then we need to again
create a tween on our camera.
It'll take about we can do 0.8 seconds again.
So tween info dot new 0.8 seconds.
And then we'll set the camera's field of view.
Field of view equal to the original field of view.
And then we'll make sure to play this tween.
Afterwards we want to make sure to reset the humanoids walk speed back to the regular speed.
And then we want to check whether or not our current stamina is equal to zero or less.
So if our current stamina is less than or equal to zero.
Then what we need to do is we need to enforce our cool down basically.
So we're going to set current stamina to zero, and then we're going to check if sprinting cooldown
is set to true.
If it is then we're going to return, because then what we're going to do is we're going to set sprinting
cooldown equal to true.
We're going to set can replenish stamina equal to false.
We're going to set shift down equal to false just in case.
And then we're going to wait for our sprint to cool down.
Now, it's very important that we have this variable here to block any other threads of execution from
running this code down here, because this function is going to be executed many times per second.
All right.
This is firing for every single frame.
So we need to block any other threads from executing.
That way we don't have any, you know, conflicting threads trying to edit settings or stamina at the
same time.
Otherwise, after we wait for our sprint cooldown, then we can set can replenish stamina equal to true.
And once that's done, we can have another if statement down here for regaining the stamina of the player.
So if the current stamina of our player is less than our max stamina.
Then what we need to do is we need to check whether or not we can actually replenish stamina.
So if we cannot replenish stamina, then we just need to return.
Otherwise.
We also need to check whether or not the player is sprinting.
So if we are not sprinting.
Or our humanoid move direction dot magnitude is less than or equal to zero.
Then we can start to regain stamina so our current stamina can be set to itself.
So plus equal stamina increase.
And then again we have to multiply this number by our delta time.
That way if players have different frame rates, they will still be regaining stamina at the same pace
as another player.
And then we're also going to make sure to set sprinting cooldown equal to false here.
So that way we can go back into this if statement and do our sprint cooldown again when we need to.
And then at the very end, what we can do is we can update our stamina bar.
So what we need to do in this function is we first need to check whether or not our guy is enabled,
because by default, our stamina guy is not going to be enabled and we need to enable it.
And then we need to fade these two different elements onto the screen.
So if I actually enable the transparency here.
So with the border there's an outline here that I need to enable the transparency for.
So we'll make that opaque.
And then we also have a fill in here that we need to enable the transparency for.
So the idea is when the player sprints this fill bar is going to go down until it hits zero.
And then it's going to slowly replenish again.
And then once it's fully replenished then we're going to fade this guy back out.
What we need to do is set this back to be transparent again, and then we need to disable this guy.
And then we're going to go back in here and we're going to check if our guy is enabled or not.
So if not guy dot enabled then we need to set guy dot enabled equal to true.
And then we need to fade those two UI elements onto the screen so we can create a tween on our guy dot
border dot outline.
So this UI stroke here we need to fade this in.
And we're going to do tween info dot new and can do something like 0.3 seconds.
And we need to change the transparency equal to zero.
So it's fully opaque.
And then we can play this tween.
And then we also need to fade in that fill bar.
So guy dot border dot fill again tween info dot new.
We'll do 0.3 seconds.
And the property we need to change on this one is the background transparent agency.
And that needs to be set to be opaque.
And then we can play that tween.
Now, the next thing we need to do is we need to set the size of our fill frame here.
So gui dot border, dot fill.
We need to set the size equal to a new Udim two that represents, um, the fraction or the percentage
of our stamina.
So what we're going to do is we're going to divide our max stamina by our current stamina to get that
percentage right.
So if our current stamina is 50 and our max stamina is 100, then that means our fill bar should be
50% or halfway filled up.
So that means what we need to do here is we need to set the width on the, uh, or the scale width on
the x axis.
That needs to be one.
By default, we want to set the offset on the x axis to zero.
And then for the offset on the y axis, we need to set that to the current stamina divided by our max
stamina to get the percentage.
And then we can set zero for the y axis offset.
And then once we do that, then we can check if the g dot boarder dot Philsys dot y becomes greater
than or equal to one.
And we also need to make sure that the g y dot boarder dot outline dot transparency is less than or
equal to zero.
So basically what's going on here is that our stamina has fully replenished and the guy is still visible
on our screen.
So in that case we need to fade out our guy to no longer be visible.
So what we're going to do is we're going to use the tween service again and create a tween on our guy
dot border dot outline.
We can do the same time of 0.3 seconds.
And we need to set the transparency to be fully transparent.
And then we can play this tween.
And then basically we can do the exact same thing for the fill as well and set this to be fully transparent.
And what am I going to do is I'm actually going to store the return from this function.
So I'm just going to call this tween.
And then we can play this tween.
And the reason I made a reference to it is because I want to listen for when this tween completes.
So tween dot completed we're going to wait.
And once the tween is completed, then we're going to set GUI dot enabled equal to false.
Now, because we are yielding here for 0.3 seconds, there might be a time where the player will sprint
in the middle of that wait statement.
So before we actually disable the visibility or the enable property for our GUI.
We want to make sure that our stamina is still filled so we can copy this here again.
And if the GUI border filled out, size dot y is still greater than or equal to one, then we can go
ahead and disable our GUI.
And guess what?
Our stamina system should be complete.
So if we go to our main story and we play test this.
We should be able to see our stamina bar appear when we sprint.
So if I hold down shift right now, as you can see, our stamina bar is not showing.
But as soon as I start walking around, it should appear.
And there we go.
It's moving around now we are getting an error in the console.
Attempt to compare number greater than or equal to a udim.
So let's go ahead and look at this real quick.
So.
Let me stop this and go to the error.
Where we can actually just open it up.
It's on line 49.
So this line right here, we are getting an error.
Oh, and that's because we actually need to grab the value off of this.
Why.
Because there are two different values.
There's an offset and there's a scale.
So right now we're just trying to compare the udim itself to a number which isn't going to work.
We actually need to grab the scale of this y axis.
And then we need to do the same thing down here okay.
Our error should be fixed.
Let's go ahead and try that out again.
So if we start to sprint, as you can see, our stamina goes down.
If I stop moving.
The stamina starts increasing, but it looks like we got another error on line 53.
Attempt to compare instance.
Uh, less than a number.
So let's go ahead and look at this problem here.
Oh.
Looks like again, we did a little bit of a mistype.
We got to type in walk speed here, not the humanoid, but we need to compare the walk speed of the
humanoid.
Okay, another error fixed.
Let's go ahead and try that again.
Okay.
And actually I think that came from did that come from or that came from our footstep handler?
Okay.
Gotcha, gotcha.
Uh, make sure you fix this error inside of your footsteps handler.
That is, uh, that is an error you will want to fix.
Okay.
Now we should be good to go.
So if I go and sprint, our stamina is increasing and we're running around.
And then once our stamina reaches zero, as you can see, we are no longer sprinting and it's not going
to regenerate after those five seconds.
As you can see, it's regenerating again.
And if I hold down shift, I'm able to sprint around and decrease the stamina.
Then it goes back down to zero.
We can't sprint, we can't do anything, and we're going to have to wait for this to slowly fill back
up.
And let's go ahead and see if our guy fades out.
So when it reaches the max, there we go.
Our guy fades out.
And then when we start to sprint again, then it reappears back onto our screen.
So that's how you can create a simple sprinting system in your games.
Let's keep working on this project and I'll see you in the next lecture.